package com.bawei.property.viewmodel

import android.util.Log
import androidx.lifecycle.viewModelScope
import com.bawei.common.entity.BaseResultEntity
import com.bawei.common.viewmodel.BaseViewModel
import com.bawei.property.entity.CarImageEntity
import com.bawei.property.intent.ParkSelectViewIntent
import com.bawei.property.model.CarApplyRepository
import com.bawei.property.uistate.ParkSelectUiState
import com.blankj.utilcode.util.GsonUtils
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flattenConcat
import kotlinx.coroutines.flow.flattenMerge
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import javax.inject.Inject

/**
 * Author: Jason Zhang
 * Date: 2024/5/29
 * Desc:
 */
@HiltViewModel
class ParkSelectViewModel @Inject constructor(private val repository: CarApplyRepository): BaseViewModel<ParkSelectViewIntent>() {
    private val _uiState = MutableStateFlow<ParkSelectUiState>(ParkSelectUiState.NoneState)
    val uiState: StateFlow<ParkSelectUiState> = _uiState.asStateFlow()

    override fun dispatchIntent(intent: ParkSelectViewIntent) {
        when(intent){
            is ParkSelectViewIntent.LoadCarColors ->  loadCarColorList()
            is ParkSelectViewIntent.UploadCarImage -> uploadCarImage(intent.list)
            is ParkSelectViewIntent.SubmitParkApply -> submitParkApply(intent.parmas)
        }
    }

    private fun submitParkApply(parmas: Any){
        viewModelScope.launch(Dispatchers.IO){
            try {
                //1.封装参数并调用接口

                //2.获取结果

                //3.通过状态流发送接到到UI页面
                withTimeout(1500L){
                    _uiState.value = ParkSelectUiState.SubmitParkApplySuccess("提交成功！")
                }
            }catch (e: Exception){
                e.printStackTrace()
            }finally {
                cancel()
            }
        }
    }


    /**
     * 多任务处理技术方案
     * 1.使用async和await来实现
     * 2.使用多个flow合并来实现
     */
    private fun uploadCarImage(list: List<CarImageEntity>){
        viewModelScope.launch(Dispatchers.IO) {
            try {
                //涉及到多张图片并行上传，使用async和await来实现
                val deferredResults = list.map {entity ->
                    async {
                        var builder = MultipartBody.Builder()
                        builder.setType(MultipartBody.FORM)
                        var body = File(entity.path).asRequestBody("multipart/form-data".toMediaTypeOrNull())
                        builder.addFormDataPart("file", entity.name, body)
                        var parts = builder.build().parts as MutableList<MultipartBody.Part>
                        repository.uploadCarImage(parts)
                    }
                }
                //等待所有结果直接完成
                var results = deferredResults.awaitAll()
                Log.i("========", "uploadCarImage: ${GsonUtils.toJson(results)}")

                var allSuccess = false
                var imgUrls = mutableListOf<String>()
                results.forEachIndexed{ index, entity ->
                    if (entity.statuesCode == "200"){
                        allSuccess = true
                        imgUrls.add("http://10.161.9.80:7035/${list[index].name}")
                    } else {
                        allSuccess = false
                    }
                }
                //发送流状态到UI层更新数据
                if (allSuccess) {
                    _uiState.value = ParkSelectUiState.UploadImageSuccess(imgUrls as List<String>)
                } else {
                    _uiState.value =ParkSelectUiState.UploadImageFail("上传失败！")
                }

            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                cancel()
            }
        }
    }


    /**
     * 使用多个Flow来合并实现多任务
     */
    private fun uploadImagesWithFlow(list: List<CarImageEntity>){
        viewModelScope.launch(Dispatchers.IO) {
            try {
                var imgUrls = mutableListOf<String>()
                //涉及到多张图片并行上传，使用async和await来实现
                val flowResults = list.map {entity ->
                    var builder = MultipartBody.Builder()
                    builder.setType(MultipartBody.FORM)
                    var body = File(entity.path).asRequestBody("multipart/form-data".toMediaTypeOrNull())
                    builder.addFormDataPart("file", entity.name, body)
                    imgUrls.add("http://10.161.9.80:7035/${entity.name}")
                    var parts = builder.build().parts as MutableList<MultipartBody.Part>
                    repository.uploadCarImageWithFlow(parts)
                }

                //var resultFlow = flowResults.asFlow().flattenConcat() //按照返回顺序
                var resultFlow = flowResults.asFlow().flattenMerge() //没有返回顺序
                resultFlow.collect{
                    var imgUrls = mutableListOf<String>()
                    var allSuccess = it.statuesCode == "200"
                    //发送流状态到UI层更新数据
                    if (allSuccess) {
                        _uiState.value = ParkSelectUiState.UploadImageSuccess(imgUrls as List<String>)
                    } else {
                        _uiState.value =ParkSelectUiState.UploadImageFail("上传失败！")
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                cancel()
            }
        }





    }


    private fun loadCarColorList(){
        viewModelScope.launch(Dispatchers.IO) {
            try {
                var result = repository.getCarColors()
                if (result.statuesCode == "200"){
                    _uiState.value = ParkSelectUiState.LoadCarColorsSuccess(result.getValues())
                }else{
                    _uiState.value = ParkSelectUiState.LoadCarColorsFail(result.msg ?: "接口加载失败！")
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                cancel()
            }
        }
    }


}